热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

关卡|白色_C语言实现推箱子游戏!(超简单详细)代码思路+源码分享

篇首语:本文由编程笔记#小编为大家整理,主要介绍了C语言实现推箱子游戏!(超简单详细)代码思路+源码分享相关的知识,希望对你有一定的参考价值。经典的推箱子是一个很古老的游

篇首语:本文由编程笔记#小编为大家整理,主要介绍了C语言实现推箱子游戏!(超简单详细)代码思路+源码分享相关的知识,希望对你有一定的参考价值。


经典的推箱子是一个很古老的游戏了,相信大家都不陌生。其目的是在训练我们的逻辑思考能力。在一个狭小的仓库中,要求把木箱放到指定的位置,稍不小心就会出现箱子无法移动或者通道被堵住的情况,所以需要巧妙的利用有限的空间和通道,合理安排移动的次序和位置,才能顺利的完成任务。

我们将编写推箱子游戏,玩家键盘控制游戏角色将所有黄色箱子推到白色方块处,效果如图所示:

操作方法:方向键↑↓←→控制移动推箱子,将箱子推到对应位置。

首先学习字符串与字符数组的概念,并应用字符数组初始化关卡数据;然后利用键盘控制游戏角色移动,实现地图元素更新和游戏胜利的判断;接着利用三维字符数组,实现多关卡的游戏;最后学习基于文件的关卡数据读取,利用枚举类型改进游戏代码。

源码:

#include
#include
#include
#define B_SIZE 60 // 方块大小
#define B_NUM 8 // 方块个数,一共8*8个方块
struct Player // 结构体,用于记录玩家位置
int i;
int j;
;
Player player; // 玩家全局变量
enum Element // 定义枚举类型,小方块所有的可能的种类
wall,target,box,empty,achieved,role
;
// 用于存储地图数据,用枚举类型实现
Element level[B_NUM][B_NUM] =
wall,wall,wall,wall,wall,wall,wall,wall,
wall,wall,wall,target,box,empty,empty,wall,
wall,empty,empty,empty,empty,empty,empty,wall,
wall,empty,empty,empty,empty,empty,empty,wall,
wall,empty,empty,empty,empty,empty,empty,wall,
wall,role,empty,box,target,wall,wall,wall,
wall,empty,empty,empty,empty,wall,wall,wall,
wall,wall,wall,wall,wall,wall,wall,wall;
int targetNum,achievedNum; // 目标位置个数、完成目标个数
void startup() // 初始化函数
initgraph(B_NUM*B_SIZE,B_NUM*B_SIZE); // 新开一个画面
setbkcolor(RGB(150,150,150)); // 灰色背景
BeginBatchDraw(); // 开始批量绘图
int i,j;
targetNum = 0; // 目标个数,初始为0
// 对二维数组遍历
for (i=0;i for (j=0;j
if (level[i][j]==role) // 找到地图中player位置

player.i = i; // 设定player位置
player.j = j; //
level[i][j]=empty; // 把地图元素变成空白empty

else if (level[i][j]==target || level[i][j]==achieved ) // 如果元素是target或achieved
targetNum++; // 目标个数+1

void show() // 绘制函数
int i,j;
cleardevice(); // 以背景颜色清空屏幕
// 遍历关卡二维数组数据
for (i=0;i
for (j=0;j
if (level[i][j]==empty) // empty 元素是空白区域

setfillcolor(RGB(150,150,150)); // 绘制灰色地面
setlinecolor(RGB(150,150,150));
fillrectangle(j*B_SIZE,i*B_SIZE,(j+1)*B_SIZE,(i+1)*B_SIZE);

else if (level[i][j]==wall) // wall 元素是墙

setfillcolor(RGB(155,0,0));
setlinecolor(RGB(150,150,150)); // 绘制淡红色、灰色线的方框
fillrectangle(j*B_SIZE,i*B_SIZE,(j+1)*B_SIZE,(i+1)*B_SIZE);

else if (level[i][j]==box) // box 元素是可移动的箱子

setfillcolor(RGB(255,255,0)); // 绘制一个黄色的方块
setlinecolor(RGB(150,150,150));
fillrectangle(j*B_SIZE,i*B_SIZE,(j+1)*B_SIZE,(i+1)*B_SIZE);

else if (level[i][j]==target) // target 元素是目标

setfillcolor(RGB(250,250,250)); // 绘制一个白色的小方块
fillrectangle((j+0.3)*B_SIZE,(i+0.3)*B_SIZE,
(j+0.7)*B_SIZE,(i+0.7)*B_SIZE);

else if (level[i][j]==achieved) // achieved 元素是已完成目标

setlinecolor(RGB(150,150,150));
setfillcolor(RGB(255,255,0)); // 绘制一个黄色的方块
fillrectangle(j*B_SIZE,i*B_SIZE,(j+1)*B_SIZE,(i+1)*B_SIZE);
setfillcolor(RGB(250,250,250)); // 绘制一个白色的小方块
fillrectangle((j+0.3)*B_SIZE,(i+0.3)*B_SIZE,
(j+0.7)*B_SIZE,(i+0.7)*B_SIZE);



// 以下绘制玩家,绘制一个人脸图案
i = player.i;
j = player.j;
setfillcolor(RGB(255,0,0));
fillcircle((j+0.5)*B_SIZE,(i+0.5)*B_SIZE,0.4*B_SIZE);//一个红色圆脸
setfillcolor(RGB(80,80,80));
setlinecolor(RGB(80,80,80));
fillcircle((j+0.3)*B_SIZE,(i+0.45)*B_SIZE,0.08*B_SIZE);//两个黑色眼睛
fillcircle((j+0.7)*B_SIZE,(i+0.45)*B_SIZE,0.08*B_SIZE);
setlinestyle(PS_SOLID,3);
line((j+0.35)*B_SIZE,(i+0.7)*B_SIZE,(j+0.65)*B_SIZE,(i+0.7)*B_SIZE);//深灰色嘴巴
setlinestyle(PS_SOLID,1);
if (achievedNum==targetNum) // 如完成目标个数==目标个数

setbkmode(TRANSPARENT); // 透明显示文字
settextcolor(RGB(0,255,255)); // 设置字体颜色
settextstyle(80, 0, _T("宋体")); // 设置字体大小、样式
outtextxy(80,200,_T("游戏胜利")); // 显示游戏胜利文字

FlushBatchDraw(); // 开始批量绘制
void update() // 每帧更新运行
if(kbhit() && (achievedNum
char input = getch(); // 获取按键
if (input=='a' || input=='s' || input=='d' || input=='w') // 如果是有效按键

int goal_i = player.i; // 移动的目标位置
int goal_j = player.j;
int goalNext_i = goal_i; // 目标位置再向前的一个位置
int goalNext_j = goal_j;
// 根据用户的不同按键输入,获得目标位置、再向前的一个位置
if (input=='a') // 向左

goal_j = player.j -1 ; // 目标位置在玩家位置的左边
goalNext_j = goal_j-1; // 目标的下一个位置,在其再左边

else if (input=='d') // 向右

goal_j = player.j +1 ; // 目标位置在玩家位置的右边
goalNext_j = goal_j+1; // 目标的下一个位置,在其再右边

else if (input=='s') // 向下

goal_i = player.i+1; // 目标位置在玩家位置的下边
goalNext_i = goal_i+1; // 目标的下一个位置,在其再下边

else if (input=='w') // 向上

goal_i = player.i-1; // 目标位置在玩家位置的上边
goalNext_i = goal_i-1; // 目标的下一个位置,在其再上边

// 根据不同地图元素的情况,判断如何移动角色和更新地图元素
if (level[goal_i][goal_j]==empty || level[goal_i][goal_j]==target )
// 如果目标位置是empty,或者target
player.i = goal_i; // 玩家移动到目标位置
player.j = goal_j;

else if (level[goal_i][goal_j]==box && level[goalNext_i][goalNext_j]==empty )
// 如果目标位置是box,再前面一个是empty
player.i = goal_i; // 玩家移动到目标位置
player.j = goal_j;
level[goal_i][goal_j]=empty; // 目标位置变成empty
level[goalNext_i][goalNext_j]=box; // 再前面变成box

else if (level[goal_i][goal_j]==box && level[goalNext_i][goalNext_j]==target)
// 如果目标位置是box,再前面一个是target
player.i = goal_i; // 玩家移动到目标位置
player.j = goal_j;
level[goal_i][goal_j] = empty; // 目标位置变成empty
level[goalNext_i][goalNext_j] = achieved; // 再前面变成achieved

else if (level[goal_i][goal_j]==achieved && level[goalNext_i][goalNext_j]== empty)
// 如果目标位置是achieved,再前面一个是empty
player.i = goal_i; // 玩家移动到目标位置
player.j = goal_j;
level[goal_i][goal_j] = target; // 目标位置变成target
level[goalNext_i][goalNext_j] = box; // 再前面变成box

else if (level[goal_i][goal_j]==achieved && level[goalNext_i][goalNext_j]== target)
// 如果目标位置是achieved,再前面一个是target
player.i = goal_i; // 玩家移动到目标位置
player.j = goal_j;
level[goal_i][goal_j] = target; // 目标位置变成target
level[goalNext_i][goalNext_j] = achieved; // 再前面变成achieved

else // 其他情况都推不动
return; // 不做任何处理,函数直接返回

achievedNum = 0; // 完成目标个数,初始为0
int i,j;
for (i=0;i for (j=0;j if (level[i][j]==achieved) // 如果元素是achieved
achievedNum++; // 完成目标个数+1

int main() // 主函数
startup(); // 初始化
while (1) // 游戏主循环

show(); // 绘制
update(); // 更新

return 0;

主要讲解了字符串与字符数组、文件读写、枚举类型等语法知识,实现了推箱子游戏。读者可以尝试在本章代码基础上继续改进:

1、实现多关卡的选择界面;

2、实现某一步移动的撤销功能(类似于下棋游戏中的悔棋功能);

3、实现按'h'键后进行提示,播放正确步骤动画的功能;

4、实现一个图形编辑器,并将设计的关卡信息保存为txt文件。

作者:童晶

希望对大家有帮助!

此外,我也给大家分享我收集的其他资源,从最零基础开始的教程到C语言C++项目案例,帮助大家在学习C语言的道路上披荆斩棘!

整理分享(多年学习的源码、项目实战视频、项目笔记,基础入门教程)最重要的是你可以在群里面交流提问编程问题哦!

欢迎转行和学习编程的伙伴,利用更多的资料学习成长比自己琢磨更快哦!(↓↓↓↓↓↓)



推荐阅读
  • 前言--页数多了以后需要指定到某一页(只做了功能,样式没有细调)html ... [详细]
  • 本文介绍了如何使用JQuery实现省市二级联动和表单验证。首先,通过change事件监听用户选择的省份,并动态加载对应的城市列表。其次,详细讲解了使用Validation插件进行表单验证的方法,包括内置规则、自定义规则及实时验证功能。 ... [详细]
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • 在金融和会计领域,准确无误地填写票据和结算凭证至关重要。这些文件不仅是支付结算和现金收付的重要依据,还直接关系到交易的安全性和准确性。本文介绍了一种使用C语言实现小写金额转换为大写金额的方法,确保数据的标准化和规范化。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 本文详细介绍了 GWT 中 PopupPanel 类的 onKeyDownPreview 方法,提供了多个代码示例及应用场景,帮助开发者更好地理解和使用该方法。 ... [详细]
  • 本题探讨了一种字符串变换方法,旨在判断两个给定的字符串是否可以通过特定的字母替换和位置交换操作相互转换。核心在于找到这些变换中的不变量,从而确定转换的可能性。 ... [详细]
  • Explore a common issue encountered when implementing an OAuth 1.0a API, specifically the inability to encode null objects and how to resolve it. ... [详细]
  • 技术分享:从动态网站提取站点密钥的解决方案
    本文探讨了如何从动态网站中提取站点密钥,特别是针对验证码(reCAPTCHA)的处理方法。通过结合Selenium和requests库,提供了详细的代码示例和优化建议。 ... [详细]
  • 数据管理权威指南:《DAMA-DMBOK2 数据管理知识体系》
    本书提供了全面的数据管理职能、术语和最佳实践方法的标准行业解释,构建了数据管理的总体框架,为数据管理的发展奠定了坚实的理论基础。适合各类数据管理专业人士和相关领域的从业人员。 ... [详细]
  • 深入理解Cookie与Session会话管理
    本文详细介绍了如何通过HTTP响应和请求处理浏览器的Cookie信息,以及如何创建、设置和管理Cookie。同时探讨了会话跟踪技术中的Session机制,解释其原理及应用场景。 ... [详细]
  • 主要用了2个类来实现的,话不多说,直接看运行结果,然后在奉上源代码1.Index.javaimportjava.awt.Color;im ... [详细]
  • 深入理解Java中的volatile、内存屏障与CPU指令
    本文详细探讨了Java中volatile关键字的作用机制,以及其与内存屏障和CPU指令之间的关系。通过具体示例和专业解析,帮助读者更好地理解多线程编程中的同步问题。 ... [详细]
  • 本文详细介绍了Akka中的BackoffSupervisor机制,探讨其在处理持久化失败和Actor重启时的应用。通过具体示例,展示了如何配置和使用BackoffSupervisor以实现更细粒度的异常处理。 ... [详细]
  • Android 渐变圆环加载控件实现
    本文介绍了如何在 Android 中创建一个自定义的渐变圆环加载控件,该控件已在多个知名应用中使用。我们将详细探讨其工作原理和实现方法。 ... [详细]
author-avatar
爱夫777
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有